const { UserModel, CodeModel } = require('../../models/index')
const { Op } = require('sequelize')
const jwtUtils = require('../../utils/jwtUtils')
const crypto = require('crypto')
// 引入阿里云短信服务模块
const Dysmsapi20170525 = require('@alicloud/dysmsapi20170525')
const { Config } = require('@alicloud/openapi-client');
const { RuntimeOptions } = require('@alicloud/tea-util');
// 短信签名名称
const SignName = '乐游汇'
// 短信模板Code
const TemplateCode = 'SMS_474955352'

// 生成6位数验证码函数
const generateCode = () => {
  return crypto.randomInt(100000, 999999).toString()
}

//初始化阿里云短信服务客户端
const createClient = () => {
  const config = new Config({
    accessKeyId: 'LTAI5tQoqau2xgbgYeKjJd5f',
    accessKeySecret: 'jpq2BeuLbaBkHSB2sOEjBXezy9M1sF',
    endpoint: 'dysmsapi.aliyuncs.com'
  })

  return new Dysmsapi20170525.default(config)
}

// 获取手机短信验证码
const getPhoneCode = async (req, res) => {
  try {
    // 获取前端传递的手机号码
    const phoneNumber = req.body.phone

    // 手机号码不存在的情况
    if (!phoneNumber) {
      return res.status(400).json({
        error: '手机号码不能为空！'
      })
    }

    // 校验手机号码格式是否合法
    const phoneRegex = /^(?:(?:\+|00)86)?1(?:(?:3[\d])|(?:4[5-79])|(?:5[0-35-9])|(?:6[5-7])|(?:7[0-8])|(?:8[\d])|(?:9[1589]))\d{8}$/
    if (!phoneRegex.test(phoneNumber)) {
      return res.status(400).json({
        error: '请输入正确的手机号码！'
      })
    }

    // 检查手机号是否已被封禁
    const phoneStatus = await UserModel.findOne({
      where: {
        phone: phoneNumber
      }
    })
    if (phoneStatus && phoneStatus.status === '封禁') {
      return res.status(400).json({
        error: '账号已被封禁'
      })
    }

    // 初始化客户端
    const client = createClient()

    // 生成6位短信验证码
    const code = generateCode()

    // 计算短信验证码过期时间
    const expiresAt = new Date()
    expiresAt.setMinutes(expiresAt.getMinutes() + 5)

    // 查询数据库中是否已存在对应手机号的验证码记录 
    const phoneRecord = await CodeModel.findOne({
      where: {
        phone: phoneNumber,
      }
    })

    // 如果已经存在验证码记录，则更新它 
    if (phoneRecord) {
      await phoneRecord.update({
        phone: phoneNumber,
        code: code,
        expiresAt: expiresAt,
        is_used: 0
      })
    } else {
      // 如果不存在则创建一条新纪录
      await CodeModel.create({
        phone: phoneNumber,
        code: code,
        expiresAt: expiresAt
      })
    }

    // 发送短信验证码
    const sendSmsRequest = new Dysmsapi20170525.SendSmsRequest({
      phoneNumbers: phoneNumber,
      signName: SignName,
      templateCode: TemplateCode,
      templateParam: `{"code":"${code}"}`
    })
    const runtime = new RuntimeOptions({})
    const codeMessage = await client.sendSmsWithOptions(sendSmsRequest, runtime)

    res.status(200).json({
      title: '获取短信验证码成功',
      data: codeMessage.body
    })
  } catch (error) {
    res.status(500).json({
      error: error.message
    })
  }
}

// 用户登录注册功能
const userAuth = async (req, res) => {
  try {
    // 获取前端发过来的用户手机号和验证码
    const { phone, code } = req.body
    if (!phone || !code) {
      return res.status(400).json({
        error: '手机号或验证码不能为空'
      })
    }

    // 在验证码表中查找对应的验证码记录并检查是否过期或已经使用
    const codeRecord = await CodeModel.findOne({
      where: {
        phone: phone,
        code: code,
        expiresAt: {
          [Op.gt]: new Date()
        },
        is_used: 0
      }
    })

    // 没有查找到的情况
    if (!codeRecord) {
      return res.status(400).json({
        error: '验证码错误'
      })
    }

    //找到的情况下说明验证码验证成功，接下来执行用户登录或注册逻辑
    let userRecord = await UserModel.findOne({
      attributes: ['user_id', 'username', 'avatar'],
      where: {
        phone: phone
      }
    })
    // 如果用户不存在则创建用户
    if (!userRecord) {
      userRecord = await UserModel.create({ phone: phone, status: '正常' })
    }
    // 更新验证码表内的验证码状态
    await codeRecord.update({ is_used: 1 })
    // 生成JWT令牌
    const token = jwtUtils.generateToken(userRecord.user_id, 'front')

    // 返回JWT令牌给用户
    res.status(200).json({
      title: '登录/注册成功',
      data: {
        token: token,
        user_id: userRecord.user_id,
        username: userRecord.username,
        avatar: userRecord.avatar
      }
    })
  } catch (error) {
    res.status(500).json({
      error: error.message
    })
  }
}

module.exports = {
  getPhoneCode,
  userAuth
}